/* list_fc.c: fontman engine, fontconfig backend */

#include "libfontman.h"
#include "internal.h"

extern fontman_list_t list_context;

int fontman_list_platform_init()
{
    FcPattern   *pat = NULL;
    FcObjectSet *os;

    if (FcInit() != FcTrue)
        return FONTMAN_ERR_PLATFORM_INIT;

    pat = FcPatternCreate();
    os  = FcObjectSetBuild(FC_FAMILY, FC_STYLE, (char *) 0);

    /* In all these cases, we needs path to do further 
     * determination (fnmatch/create ft_face) */
    if (list_context.flags & FONTMAN_GET_PS_NAME    ||
        list_context.flags & FONTMAN_GET_LOCAL_NAME ||
        ! (list_context.flags & FONTMAN_INCLUDE_ALL))
        list_context.flags |= FONTMAN_GET_PATH;

    if (list_context.flags & FONTMAN_GET_PATH)
        FcObjectSetAdd(os, FC_FILE);

    list_context.u.fc.list = FcFontList(0, pat, os);
    FcObjectSetDestroy(os);
    if (pat)
        FcPatternDestroy(pat);
    
    list_context.u.fc.count = 0;

    return 0;
}

void fontman_list_platform_free()
{
    if (list_context.u.fc.list)
        FcFontSetDestroy(list_context.u.fc.list);

    FcFini();
}

int fontman_list_platform_next(fontman_face_t *face)
{
    FcFontSet *list;
    unsigned int flags;
    int count;

    list = list_context.u.fc.list;
    count = list_context.u.fc.count++;
    if (count >= list->nfont)
        return FONTMAN_ERR_NO_NEXT;

    flags = list_context.flags;

    if (flags & FONTMAN_GET_PATH)
    {
        char *path;

        FcPatternGetString(list->fonts[count], FC_FILE, 0, 
                           (FcChar8 **) &path);

        strncpy(face->path, path, PATH_MAX - 1);

        if (fnmatch(FONTMAN_FILE_NAME_PATTERN, 
                    path, FNM_CASEFOLD) != 0)
            return fontman_list_platform_next(face);

        if (flags & FONTMAN_GET_PS_NAME ||
            flags & FONTMAN_GET_LOCAL_NAME)
        {
            int err;

            /* we can get name by ourselves, so no need for
             * FreeType to get that for us */
            err = fontman_get_font_info(&list_context.lib, face, 
                                        flags & ~FONTMAN_GET_NAME);
            if (err)
                return err;

            if (flags & FONTMAN_GET_LOCAL_NAME &&
                ! (flags & FONTMAN_INCLUDE_ALL) &&
                strlen(face->local_name) == 0)
                return fontman_list_platform_next(face);
        }
    }

    if (flags & FONTMAN_GET_NAME)
    {
        char *name, *style;

        FcPatternGetString(list->fonts[count], FC_FAMILY, 0, 
                           (FcChar8 **) &name);
        
        FcPatternGetString(list->fonts[count], FC_STYLE, 0, 
                           (FcChar8 **) &style);

        strncpy(face->name, name, FONTMAN_MAX_FONT_NAME - 1);
        strcat(face->name, ", ");
        strcat(face->name, style);
    }

    return 0;
}

int fontman_info_platform_font(fontman_face_t *face)
{
    FcFontSet   *fs;
    FcPattern   *pat = NULL;
    FcObjectSet *os;
    char        *path, *style = NULL;
    int          i, len;

    if (FcInit() != FcTrue)
        return FONTMAN_ERR_PLATFORM_INIT;

    /* Because fontconfig don't support full name query (weird 
     * enough), we have to use the following trick to separate
     * family name and style */
    len = strlen(face->name);
    for (i = len - 1; i >= 0; i--)
        if (face->name[i] == ',' && i + 2 < len)
        {
            style = &(face->name[i + 2]);
            face->name[i] = '\0';
            break;
        }

    pat = FcPatternCreate();
    FcPatternAddString(pat, FC_FAMILY, (FcChar8 *) face->name);
    if (style != NULL)
        FcPatternAddString(pat, FC_STYLE, (FcChar8 *) style);
    
    /* we used the separated name for fontconfig query, now 
     * restore (connect with style) it */
    if (i > 0)
        face->name[i] = ',';

    os = FcObjectSetBuild(FC_FILE, (char *) 0);
    fs = FcFontList(0, pat, os);

    FcObjectSetDestroy(os);
    if (pat)
        FcPatternDestroy(pat);

    if (fs == NULL || fs->nfont <= 0)
    {
        FcFini();
        return FONTMAN_ERR_FIND_FONT;
    }

    FcPatternGetString(fs->fonts[0], FC_FILE, 0, 
                       (FcChar8 **) &path);
    FcFini();

    strncpy(face->path, path, PATH_MAX - 1);

    return fontman_info_file(face, 
                             FONTMAN_GET_ALL & 
                             ~FONTMAN_GET_NAME);
}

